#include "PreCompiled.h"
#include "DockWindowManager.h"
#include "MainWindow.h"
DockWindowItems::DockWindowItems()
{
 
}
DockWindowItems::~DockWindowItems()
{

}

void DockWindowItems::addDockWidget(const char* name,Qt::DockWidgetArea pos,bool visibility,bool tabbed)
{
	DockWindowItem item;
	item.name = name;
	item.pos = pos;
	item.visibility = visibility;
	item.tabbed = tabbed;

	_items <<item;
}
void DockWindowItems::setDockingArea(const char* name,Qt::DockWidgetArea pos)
{
	for(QList<DockWindowItem>::Iterator it = _items.begin();it != _items.end();it++)
	{
		if(it->name == QLatin1String(name))
		{
			it->pos = pos;
			break;
		}
	}
}

void DockWindowItems::setVisibility(const char* name,bool v)
{
	for (QList<DockWindowItem>::Iterator it = _items.begin(); it != _items.end(); it++)
	{
		if(it->name == QLatin1String(name))
		{
			it->visibility = v;
			break;
		}
	}
}
void DockWindowItems::setVisibility(bool v)
{
	for(QList<DockWindowItem>::Iterator it = _items.begin(); it != _items.end();it++)
	{
		it->visibility = v;
	}
}
const QList<DockWindowItem>& DockWindowItems::dockWidgets()const
{
	return this->_items;
}

// -------------------------------------------------------------------- [4/9/2013 Administrator]
struct DockWindowManagerP
{
   QList<QDockWidget*> _dockedWindows;
   QMap<QString,QPointer<QWidget>> _dockWindows;
   DockWindowItems _dockWindiwItems;
};
DockWindowManager* DockWindowManager::_instance = 0;

DockWindowManager::DockWindowManager(void)
{
   d = new DockWindowManagerP;
}

DockWindowManager::~DockWindowManager(void)
{
	d->_dockWindows.clear();
	delete d;
}

DockWindowManager* DockWindowManager::instance()
{
   if(_instance == 0)
	   _instance = new DockWindowManager;
   return _instance;
}

void DockWindowManager::destruct()
{
	delete _instance;
	_instance = 0;
}

bool DockWindowManager::registerDockWindow(const char* name,QWidget* widget)
{
	QMap<QString,QPointer<QWidget>>::Iterator it = d->_dockWindows.find(QLatin1String(name));
	if(it != d->_dockWindows.end() || !widget)
		return false; 
	d->_dockWindows[QLatin1String(name)] = widget;
	widget->hide();
	return true;
}

QDockWidget* DockWindowManager::addDockWindow(const char* name,QWidget* widget,Qt::DockWidgetArea pos/* = Qt::AllDockWidgetAreas */)
{ 
	MainWindow* mw = getMainWindow();
	QDockWidget* dw = new QDockWidget(mw);
	dw->hide();
	switch(pos)
	{
	case Qt::LeftDockWidgetArea:
	case Qt::BottomDockWidgetArea:
	case Qt::RightDockWidgetArea:
	case  Qt::TopDockWidgetArea:
		mw->addDockWidget(pos,dw);
	default:
		break;
	}

	connect(dw,SIGNAL(destroyed(QObject*)),this,SLOT(onDockWidgetDestroyed(QObject*)));
	connect(widget,SIGNAL(destroyed(QObject*)),this,SLOT(OnWidgetDestroyed(QObject*)));

	widget->setParent(dw);
	dw->setWidget(widget);

	dw->setObjectName(QLatin1String(name));
	dw->setWindowTitle(QDockWidget::trUtf8(name));
	dw->setFeatures(QDockWidget::AllDockWidgetFeatures);

	d->_dockedWindows.push_back(dw);

	return dw; 
}
QWidget* DockWindowManager::removeDockWindow(const char* name)
{
   QWidget* widget = 0;
   for(QList<QDockWidget*>::Iterator it = d->_dockedWindows.begin(); it != d->_dockedWindows.end(); it++)
   {
	   if((*it)->objectName() == QLatin1String(name))
	   {
          QDockWidget* dockwidget = *it;
		   d->_dockedWindows.erase(it);
		   getMainWindow()->removeDockWidget(dockwidget);
		   widget = dockwidget->widget();
		   dockwidget->setParent(0);
		   dockwidget->setWidget(0);
		   disconnect(widget,SIGNAL(destroyed(QObject*)),this,SLOT(OnWidgetDestroyed(QObject*)));
		   disconnect(dockwidget,SIGNAL(destroyed(QObject*)),this,SLOT(onDockWidgetDestroyed(QObject*)));

		   delete dockwidget;
		   break;   
	   }
   }
   return widget;
}
void DockWindowManager::removeDockWindow(QWidget* widget)
{
	for (QList<QDockWidget*>::Iterator it = d->_dockedWindows.begin(); it != d->_dockedWindows.end(); it++)
   {
	   if((*it)->widget() == widget)
	   {
		   QDockWidget* dw = (*it);
		   //QWidget* widget = dw->widget();
		   d->_dockedWindows.erase(it);
		   getMainWindow()->removeDockWidget(dw);
		   widget->setParent(0);
		   dw->setWidget(0);
		   disconnect(dw,SIGNAL(destroyed(QObject*)),this,SLOT(onDockWidgetDestroyed(QObject*)));
		   disconnect(widget,SIGNAL(destroyed(QObject*)),this,SLOT(OnWidgetDestroyed(QObject*)));
		   delete dw;
		   break;
	   }
   }
}

void DockWindowManager::setup(DockWindowItems* items)
{
    d->_dockWindiwItems = *items;
	QList<QDockWidget*> docked = d->_dockedWindows;
	const QList<DockWindowItem> dws = items->dockWidgets();
	for(QList<DockWindowItem>::ConstIterator it = dws.begin();it != dws.end();it++)
	{
		QDockWidget* dw = findDockWidget(docked,it->name);
		if(!dw)
		{
			QMap<QString,QPointer<QWidget>>::ConstIterator jt = d->_dockWindows.find(it->name);
			if(jt != d->_dockWindows.end())
			{
				dw = addDockWindow(jt.value()->objectName().toUtf8(),jt.value(),it->pos);
				jt.value()->show();
				dw->toggleViewAction()->setData(it->name);
				dw->setVisible(true);
			}		
		}else
		{
			dw->setVisible(true);
			dw->toggleViewAction()->setVisible(true);
			int index = docked.indexOf(dw);
			docked.removeAt(index);

		}
	}

}
QWidget* DockWindowManager::getDockWindow(const char* name)const
{
	for (QList<QDockWidget*>::ConstIterator it = d->_dockedWindows.begin();it != d->_dockedWindows.end();it++)
   {
	   if((*it)->objectName() == QLatin1String(name))
		   return *it;
   }
	return 0;
}
QList<QWidget*> DockWindowManager::getDockWindows()const
{
     QList<QWidget*> docked;
	 for(QList<QDockWidget*>::ConstIterator it = d->_dockedWindows.begin(); it != d->_dockedWindows.end(); it++)
	 {
           docked.push_back((*it)->widget());
	 }
	 return docked;
}

QDockWidget* DockWindowManager::findDockWidget(const QList<QDockWidget*>& docked,const QString& name)const
{
	for (QList<QDockWidget*>::ConstIterator it = docked.begin(); it != docked.end();it++)
	{
       if((*it)->toggleViewAction()->data().toString() == name)
         return *it;
	}
	return 0;
}

//-signal
void DockWindowManager::onDockWidgetDestroyed(QObject* o)
{
	for (QList<QDockWidget*>::Iterator it = d->_dockedWindows.begin(); it != d->_dockedWindows.end(); it++)
   {
	   if((*it) == o)
	   {
		   d->_dockedWindows.erase(it);
		   break;
	   }
   }
}

void DockWindowManager::OnWidgetDestroyed(QObject* widget)
{
	for (QList<QDockWidget*>::Iterator it = d->_dockedWindows.begin(); it != d->_dockedWindows.end(); it++)
   {
	   if((*it)->metaObject() != &QDockWidget::staticMetaObject)
	   {
		   disconnect(*it,SIGNAL(destroyed(QObject*)),this,SLOT(onDockWidgetDestroyed(QObject*)));
		   d->_dockedWindows.erase(it);
		   break;   
	   }
	   if((*it)->widget() == widget)
	   {
		   QDockWidget* dw = *it;
		   dw->deleteLater();
		   break;
	   }
   }
}

#include "moc_DockWindowManager.cpp"
